home *** CD-ROM | disk | FTP | other *** search
/ InfoMagic Internet Tools 1993 July / Internet Tools.iso / RockRidge / security / xinetd / xinetd.2.0.6 / init.c < prev    next >
Encoding:
C/C++ Source or Header  |  1993-01-22  |  6.2 KB  |  305 lines

  1. /*
  2.  * (c) Copyright 1992 by Panagiotis Tsirigotis
  3.  * All rights reserved.  The file named COPYRIGHT specifies the terms 
  4.  * and conditions for redistribution.
  5.  */
  6.  
  7. static char RCSid[] = "$Id: init.c,v 5.1 1992/11/01 00:01:21 panos Exp $" ;
  8.  
  9. #include <sys/types.h>
  10. #include <sys/time.h>
  11. #include <sys/resource.h>
  12. #include <syslog.h>
  13. #include <fcntl.h>
  14.  
  15. #include "sio.h"
  16. #include "str.h"
  17. #include "pset.h"
  18. #include "xlog.h"
  19.  
  20. #include "options.h"
  21.  
  22. #include "defs.h"
  23. #include "config.h"
  24. #include "state.h"
  25. #include "conf.h"
  26.  
  27.  
  28. struct module
  29. {
  30.     char *name ;
  31.     status_e (*initializer)() ;
  32. } ;
  33.  
  34.  
  35. status_e msg_init() ;
  36. status_e service_init() ;
  37. status_e server_init() ;
  38. status_e conn_init() ;
  39. status_e addrlist_init() ;
  40. status_e interval_init() ;
  41. status_e signal_init() ;
  42. status_e initenv() ;
  43.  
  44. static struct module program_modules[] = 
  45.     {
  46.         { "service",                        svc_init            },
  47.         { "server",                            server_init        },
  48.         { "connection",                    conn_init        },
  49.         { "addrlist",                        addrlist_init    },
  50.         { "time intervals",                interval_init    },
  51.         { "signal",                            signal_init        },
  52.         { "environment",                    initenv            },
  53.         { CHAR_NULL }
  54.     } ;
  55.  
  56.  
  57. /*
  58.  * Keep open descriptors 0..DONT_CLOSE
  59.  */
  60. #define DONT_CLOSE                2
  61.  
  62. extern int sys_nerr;
  63. extern char *sys_errlist[];
  64. extern int errno;
  65.  
  66. void msg() ;
  67.  
  68. void exit() ;
  69.  
  70.  
  71. /*
  72.  * Perform all necessary initializations
  73.  */
  74. void init_daemon( argc, argv )
  75.     int argc ;
  76.     char *argv[] ;
  77. {
  78.     void init_common(), init_no_debug(), init_rw_state() ;
  79.  
  80.     (void) opt_recognize( argc, argv ) ;
  81.  
  82.     init_common( argc, argv ) ;
  83.  
  84.     if ( ! debug.on )
  85.         init_no_debug() ;
  86.     
  87.     init_rw_state() ;
  88. }
  89.  
  90.  
  91. /*
  92.  * This function is invoked when a system call fails during initialization.
  93.  * A message is printed to stderr, and the program is terminated
  94.  */
  95. PRIVATE void syscall_failed( call )
  96.     char *call ;
  97. {
  98.     char errno_buf[ 40 ] ;
  99.     char *err ;
  100.  
  101.     if ( errno < sys_nerr )
  102.         err = sys_errlist[ errno ] ;
  103.     else
  104.         err = strx_sprint( errno_buf, sizeof(errno_buf), "errno = %d", errno ) ;
  105.  
  106.     Sprint( 2, "%s: %s failed: %s\n", program_name, call, err ) ;
  107.     exit( 1 ) ;
  108. }
  109.  
  110.  
  111. /*
  112.  * Initializations performed regardless of debugging
  113.  */
  114. PRIVATE void init_common( argc, argv )
  115.     int argc ;
  116.     char *argv[] ;
  117. {
  118.     int fd ;
  119.     struct rlimit rl ;
  120.     char *func = "init_common" ;
  121.  
  122. #ifdef RLIMIT_NOFILE
  123.     /*
  124.      * Set the soft file descriptor limit to the hard limit.
  125.      * We do this here because getdtablesize() returns the soft limit
  126.      */
  127.     ps.ros.orig_max_descriptors = getdtablesize() ;
  128.     if ( getrlimit( RLIMIT_NOFILE, &rl ) != -1 )
  129.     {
  130.         rl.rlim_cur = rl.rlim_max ;
  131.         (void) setrlimit( RLIMIT_NOFILE, &rl ) ;
  132.     }
  133.     if ( Smorefds() == SIO_ERR )
  134.         syscall_failed( "malloc" ) ;
  135. #endif    /* RLIMIT_NOFILE */
  136.  
  137.     debug.on = d_option ;
  138.  
  139.     ps.ros.Argv = argv ;
  140.     ps.ros.Argc = argc ;
  141.    ps.ros.config_file = f_option ? f_option_arg : DEFAULT_CONFIG_FILE ;
  142.    ps.ros.max_descriptors = getdtablesize() ;
  143.     ps.ros.is_superuser = ( geteuid() == 0 ) ;
  144.     if ( limit_option )
  145.         ps.ros.process_limit = limit_option_arg ;
  146.     ps.ros.loop_rate = ( loop_option ) ? loop_option_arg : DEFAULT_LOOP_RATE ;
  147.     ps.rws.descriptors_free = ps.ros.max_descriptors - DESCRIPTORS_RESERVED ;
  148.  
  149.     for ( fd = DONT_CLOSE+1 ; fd < ps.ros.max_descriptors ; fd++ )
  150.         (void) close( fd ) ;
  151.     
  152.     xlog_parms( XLOG_SYSLOG, program_name, LOG_PID + LOG_NOWAIT, LOG_DAEMON ) ;
  153.  
  154.     /*
  155.      * The remaining functions must be called AFTER we determine 
  156.      * if debugging is enabled because their behavior depends on it
  157.      */
  158.     if ( msg_init() == FAILED )
  159.         syscall_failed( "msg_init" ) ;
  160.  
  161.     {
  162.         struct module *mp ;
  163.  
  164.         for ( mp = program_modules ; mp->name ; mp++ )
  165.             if ( (*mp->initializer)() == FAILED )
  166.             {
  167.                 msg( LOG_CRIT, func,
  168.                     "Initialization of %s facility failed. Exiting...", mp->name ) ;
  169.                 exit( 1 ) ;
  170.             }
  171.     }
  172.     (void) umask( 0 ) ;
  173. }
  174.  
  175.  
  176. /*
  177.  * Initializations performed when debugging is not enabled
  178.  */
  179. PRIVATE void init_no_debug()
  180. {
  181.     int fd ;
  182.     int root_fd ;
  183.     int tries ;
  184.     pid_t pid ;
  185.     char *func = "init_no_debug" ;
  186.     struct name_value *nv_find_value() ;
  187.     void no_control_tty() ;
  188.  
  189.     /*
  190.      * Reserve descriptors 0, 1, 2.
  191.      * We need to do this because when we start a server we
  192.      * dup the socket connection to 0, 1, 2. If those descriptors are
  193.      * not reserved, it is possible that they are assigned to syslog
  194.      * and we want to avoid that.
  195.      */
  196.     if ( ( root_fd = open( "/", O_RDONLY ) ) == -1 )
  197.         syscall_failed( "open" ) ;
  198.  
  199.     for ( fd = 0 ; fd <= DONT_CLOSE ; fd++ )
  200.         if ( root_fd != fd && dup2( root_fd, fd ) == -1 )
  201.             syscall_failed( "dup2" ) ;
  202.  
  203.     if ( root_fd > DONT_CLOSE )
  204.         (void) close( root_fd ) ;
  205.  
  206.     /*
  207.      * First fork so that the parent will think we have exited
  208.      */
  209.     for ( tries = 0 ;; tries++ )
  210.     {
  211.         if ( tries == 5 )
  212.         {
  213.             msg( LOG_CRIT, func, "fork: %m. Exiting..." ) ;
  214.             exit( 0 ) ;
  215.         }
  216.         pid = fork() ;
  217.         if ( pid == -1 )
  218.         {
  219.             sleep( 1 ) ;    /* wait for a second */
  220.             continue ;        /* and then retry        */
  221.         }
  222.         if ( pid == 0 )
  223.             break ;
  224.         else
  225.         {
  226.             sleep( 3 ) ;    /* give some time to the daemon to initialize */
  227.             if ( pid_option )
  228.                 Sprint( 2, "%d\n", pid ) ;
  229.             exit( 0 ) ;
  230.         }
  231.     }
  232.     no_control_tty() ;
  233. }
  234.  
  235.  
  236. /*
  237.  * Initialize all services
  238.  *
  239.  * This function is either successful in starting some services 
  240.  * or it terminates the program.
  241.  */
  242. void init_services()
  243. {
  244.     struct configuration conf ;
  245.     char *func = "init_services" ;
  246.     unsigned start_services() ;
  247.     status_e get_configuration() ;
  248.     void include_special_services() ;
  249.  
  250.     if ( get_configuration( &conf ) == FAILED )
  251.     {
  252.         msg( LOG_CRIT, func, "couldn't get configuration. Exiting..." ) ;
  253.         exit( 1 ) ;
  254.     }
  255.  
  256.     SVC_HOLD( conf.defaults ) ;
  257.     ps.rws.cs.defaults = conf.defaults ;
  258.  
  259.     (void) start_services( conf.services ) ;
  260.  
  261.     /*
  262.      * The number of available/active services is kept by the service functions
  263.      */
  264.     if ( ps.rws.available_services == 0 )
  265.     {
  266.         msg( LOG_CRIT, func, "no services. Exiting..." ) ;
  267.         exit( 1 ) ;
  268.     }
  269.  
  270.     include_special_services() ;
  271. }
  272.  
  273.  
  274. /*
  275.  * Create allocators and tables
  276.  */
  277. PRIVATE void init_rw_state()
  278. {
  279.     pset_h new_table() ;
  280.  
  281.    ps.rws.servers = new_table( 0 ) ;
  282.    ps.rws.retries = new_table( 0 ) ;
  283.     ps.rws.services = new_table( 0 ) ;
  284.  
  285.     FD_ZERO( &ps.rws.socket_mask ) ;
  286.     ps.rws.mask_max = 0 ;
  287.  
  288. }
  289.  
  290.  
  291. PRIVATE pset_h new_table( size )
  292.     unsigned size ;
  293. {
  294.     char *func = "new_table" ;
  295.     pset_h tab = pset_create( size, 0 ) ;
  296.  
  297.     if ( tab == NULL )
  298.     {
  299.         msg( LOG_CRIT, func, "Failed to create table" ) ;
  300.         exit( 1 ) ;
  301.     }
  302.     return( tab ) ;
  303. }
  304.  
  305.